#include "GDIPad.h"

// ======================================================================
//							GDI based sketchpad
// ======================================================================

GDIPad::GDIPad( SURFHANDLE s, HDC hdc ): Sketchpad( s ) {
	hDC = hdc;
	hFont0 = NULL;
	cfont = NULL;
	cpen = NULL;
	cbrush = NULL;
	SetViewportOrgEx( hDC, 0, 0, NULL );
	::SetTextAlign( hDC, TA_LEFT );

	// Default initial drawing settings
	SetBkMode( hDC, TRANSPARENT ); // transparent text background
	SelectObject( hDC, GetStockObject( NULL_BRUSH ) ); // no fill
	SelectObject( hDC, GetStockObject( NULL_PEN ) );   // no outline
}

GDIPad::~GDIPad() {
	// make sure to deselect custom resources before destroying the DC
	if( hFont0 )	SelectObject( hDC, hFont0 );
	if( cpen )		SelectObject( hDC, GetStockObject( NULL_PEN ) );
	if( cbrush )	SelectObject( hDC, GetStockObject( NULL_BRUSH ) );
}

oapi::Font *GDIPad::SetFont( oapi::Font *font ) const {
	oapi::Font *pfont = cfont;
	if( font ) {
		HFONT hFont = (HFONT)SelectObject( hDC, ((D3D11PadFont*)font)->hFont );
		if( !cfont )
			hFont0 = hFont;
	}
	else
		if( hFont0 ) { // restore original font
			SelectObject( hDC, hFont0 );
			hFont0 = 0;
		}
	cfont = font;
	return pfont;
}

oapi::Pen *GDIPad::SetPen( oapi::Pen *pen ) const {
	oapi::Pen *ppen = cpen;
	if( pen )
		SelectObject( hDC, ((D3D11PadPen*)pen)->hPen );
	else // disable outlines
		SelectObject( hDC, GetStockObject( NULL_PEN ) );
	cpen = pen;
	return ppen;
}

oapi::Brush *GDIPad::SetBrush( oapi::Brush *brush ) const {
	oapi::Brush *pbrush = cbrush;
    if (brush)
    	SelectObject( hDC, ((D3D11PadBrush*)brush)->hBrush );
	else // disable filled brush
        SelectObject( hDC, GetStockObject( NULL_BRUSH ) );
	cbrush = brush;
	return pbrush;
}

void GDIPad::SetTextAlign( TAlign_horizontal tah, TAlign_vertical tav ) {
	UINT align = 0;

	switch( tah ) {
		case LEFT:
			align |= TA_LEFT;
			break;
		case CENTER:
			align |= TA_CENTER;
			break;
		case RIGHT:
			align |= TA_RIGHT;
			break;
	}
	switch( tav ) {
		case TOP:
			align |= TA_TOP;
				break;
		case BASELINE:
			align |= TA_BASELINE;
			break;
		case BOTTOM:
			align |= TA_BOTTOM;
			break;
	}
	::SetTextAlign( hDC, align );
}

DWORD GDIPad::SetTextColor( DWORD col ) {
	return (DWORD)::SetTextColor( hDC, COLORREF(col) );
}

DWORD GDIPad::SetBackgroundColor( DWORD col ) {
	return (DWORD)SetBkColor( hDC, (COLORREF)col );
}

void GDIPad::SetBackgroundMode( BkgMode mode ) {
	int bkmode;
	switch( mode ) {
		case BK_TRANSPARENT:
			bkmode = TRANSPARENT;
			break;
		case BK_OPAQUE:
			bkmode = OPAQUE;
			break;
	}
	SetBkMode( hDC, bkmode );
}

DWORD GDIPad::GetCharSize() {
	TEXTMETRIC tm;
	auto res = GetTextMetrics( hDC, &tm );
	return MAKELONG( tm.tmHeight-tm.tmInternalLeading, tm.tmAveCharWidth );
}

DWORD GDIPad::GetTextWidth( const char *str, int len ) {
	SIZE size;
	if( !len )
		len = (int)strlen( str );
	GetTextExtentPoint32A( hDC, str, len, &size );
	return (DWORD)size.cx;
}

void GDIPad::SetOrigin( int x, int y ) {
    SetViewportOrgEx( hDC, x, y, NULL );
}

bool GDIPad::Text( int x, int y, const char *str, int len ) {
	return (TextOutA( hDC, x, y, str, len ) != FALSE);
}

bool GDIPad::TextBox( int x1, int y1, int x2, int y2, const char *str, int len ) {
	RECT r;
	r.left =   x1;
	r.top =    y1;
	r.right =  x2;
	r.bottom = y2;
	bool res = DrawTextA( hDC, str, len, &r, DT_LEFT | DT_NOPREFIX | DT_WORDBREAK ) != 0 ;
	return res;
}

void GDIPad::Pixel( int x, int y, DWORD col ) {
	SetPixel( hDC, x, y, (COLORREF)col );
}

void GDIPad::MoveTo( int x, int y ) {
	MoveToEx( hDC, x, y, NULL );
}

void GDIPad::LineTo( int x, int y ) {
	::LineTo( hDC, x, y );
}

void GDIPad::Line( int x0, int y0, int x1, int y1 ) {
    MoveToEx( hDC, x0, y0, NULL );
	::LineTo( hDC, x1, y1 );
}

void GDIPad::Rectangle( int x0, int y0, int x1, int y1 ) {
	::Rectangle( hDC, x0, y0, x1, y1 );
}

void GDIPad::Ellipse( int x0, int y0, int x1, int y1 ) {
	::Ellipse( hDC, x0, y0, x1, y1 );
}

void GDIPad::Polygon( const oapi::IVECTOR2 *pt, int npt ) {
	::Polygon( hDC, (const POINT*)pt, npt );
}

void GDIPad::Polyline( const oapi::IVECTOR2 *pt, int npt ) {
	::Polyline( hDC, (const POINT*)pt, npt );
}

void GDIPad::PolyPolygon( const oapi::IVECTOR2 *pt, const int *npt, const int nline ) {
	::PolyPolygon( hDC, (const POINT*)pt, npt, nline );
}

void GDIPad::PolyPolyline( const oapi::IVECTOR2 *pt, const int *npt, const int nline ) {
	::PolyPolyline( hDC, (const POINT*)pt, (const DWORD*)npt, nline );
}

//		replaced by D3D11Pad font, pen and brush.
// ======================================================================
//							GDI Font
// ======================================================================
/*
GDIFont::GDIFont( int height, bool prop, const char *face, Style style, int orientation ): oapi::Font( height, prop, face, style, orientation )
{
	char *def_fixedface = "Courier New";
	char *def_sansface = "Arial";
	char *def_serifface = "Times New Roman";

	if( !_stricmp( face, "fixed" ) )
		face = def_fixedface;
	else if( !_stricmp( face, "sans" ) )
		face = def_sansface;
	else if( !_stricmp( face, "serif" ) )
		face = def_serifface;
	else if( _stricmp( face, def_fixedface ) &&	_stricmp( face, def_sansface ) && _stricmp( face, def_serifface ) )
		face = (prop ? def_sansface : def_fixedface);

	int weight = (style & BOLD ? FW_BOLD : FW_NORMAL);
	DWORD italic = (style & ITALIC ? TRUE : FALSE);
	DWORD underline = (style & UNDERLINE ? TRUE : FALSE);
	hFont = CreateFontA( height, 0, orientation, orientation, weight, italic, underline, 0, 0, 3, 2, 1, 49, face );
}

GDIFont::~GDIFont() {
	DeleteObject( hFont );
}

// ======================================================================
//							GDI Pen
// ======================================================================

GDIPen::GDIPen( int style, int width, DWORD col ): oapi::Pen( style, width, col ) {
	int pstyle;
	switch (style) {
	case 0:
		pstyle = PS_NULL;
		break;
	case 2:
		pstyle = PS_DOT;
		break;
	default:
		pstyle = PS_SOLID;
		break;
	}
	hPen = CreatePen( pstyle, width, (COLORREF)col );
}

GDIPen::~GDIPen() {
	DeleteObject( hPen );
}

// ======================================================================
//							GDI Brush
// ======================================================================

GDIBrush::GDIBrush( DWORD col ): oapi::Brush( col ) {
	hBrush = CreateSolidBrush( (COLORREF)col );
}

GDIBrush::~GDIBrush() {
	DeleteObject( hBrush );
}
*/